﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Aquarinum.Base.Infrastructure.EventBus.Default;
using Aquarinum.Base.Infrastructure.EventBus.Interfaces;


namespace Aquarinum.Base.Infrastructure.EventBus.EventStore
{
    /// <summary>
    /// 内存EventStore
    /// </summary>
    public class DefalutInMemoryEventStore : IEventStore
    {
        #region 单例封装

        private static DefalutInMemoryEventStore _instance;
        private static readonly object Instancelocker = new object();


        private DefalutInMemoryEventStore()
        {
            _eventAndHandlerMapping = new ConcurrentDictionary<Type, IList<Type>>();
        }

        /// <summary>
        ///     单例实例
        /// </summary>
        /// <returns></returns>
        public static DefalutInMemoryEventStore GetInstance()
        {
            //没有第一重 instance == null 的话，每一次有线程进入 GetInstance()时，均会执行锁定操作来实现线程同步，
            //非常耗费性能 增加第一重instance ==null 成立时的情况下执行一次锁定以实现线程同步
            if (_instance == null)
                lock (Instancelocker)
                {
                    //Double-Check Locking 双重检查锁定
                    if (_instance == null) _instance = new DefalutInMemoryEventStore();
                }

            return _instance;
        }

        #endregion


        /// <summary>
        /// 定义锁对象
        /// </summary>
        private static readonly object LockObj = new object();

        /// <summary>
        /// HandlerMapping内存缓存(订阅data为key，)
        /// </summary>
        private readonly ConcurrentDictionary<Type, IList<Type>> _eventAndHandlerMapping;


        /// <summary>
        /// 添加handle注册（泛型）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TH"></typeparam>
        public void AddRegister<T, TH>() where T : IEventData where TH : IEventHandler
        {
            AddRegister(typeof(T), typeof(TH));
        }


        /// <summary>
        /// 添加handler
        /// </summary>
        /// <param name="eventData"></param>
        /// <param name="eventHandler"></param>
        public void AddRegister(Type eventData, Type eventHandler)
        {
            lock (LockObj)
            {
                if (!HasRegisterForEvent(eventData))
                {
                    var handlers = new List<Type>();
                    _eventAndHandlerMapping.TryAdd(eventData, handlers);
                }

                if (_eventAndHandlerMapping[eventData].All(h => h != eventHandler))
                {
                    _eventAndHandlerMapping[eventData].Add(eventHandler);
                }
            }
        }

        /// <summary>
        /// 移除handler
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TH"></typeparam>
        public void RemoveRegister<T, TH>() where T : IEventData where TH : IEventHandler
        {
            var handlerToRemove = FindRegisterToRemove(typeof(T), typeof(TH));
            RemoveRegister(typeof(T), handlerToRemove);
        }

        /// <summary>
        /// 移除handler
        /// </summary>
        /// <param name="eventData"></param>
        /// <param name="eventHandler"></param>
        public void RemoveRegister(Type eventData, Type eventHandler)
        {
            if (eventHandler != null)
            {
                lock (LockObj)
                {
                    _eventAndHandlerMapping[eventData].Remove(eventHandler);
                    if (!_eventAndHandlerMapping[eventData].Any())
                    {
                        _eventAndHandlerMapping.TryRemove(eventData, out _);
                    }
                }
            }
        }

        /// <summary>
        /// 获取store中handler
        /// </summary>
        /// <param name="eventData"></param>
        /// <param name="eventHandler"></param>
        /// <returns></returns>
        private Type FindRegisterToRemove(Type eventData, Type eventHandler)
        {
            if (!HasRegisterForEvent(eventData))
            {
                return null;
            }

            return _eventAndHandlerMapping[eventData].FirstOrDefault(eh => eh == eventHandler);
        }

        /// <summary>
        ///  判断是否已注册（泛型）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public bool HasRegisterForEvent<T>() where T : IEventData
        {
            return _eventAndHandlerMapping.ContainsKey(typeof(T));
        }

        /// <summary>
        /// 判断是否已注册
        /// </summary>
        /// <param name="eventData"></param>
        /// <returns></returns>
        public bool HasRegisterForEvent(Type eventData)
        {
            return _eventAndHandlerMapping.ContainsKey(eventData);
        }

        /// <summary>
        /// 获取泛型event所有的handler
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IEnumerable<Type> GetHandlersForEvent<T>() where T : IEventData
        {
            return GetHandlersForEvent(typeof(T));
        }

        /// <summary>
        ///  获取指定event类型所有的handler
        /// </summary>
        /// <param name="eventData"></param>
        /// <returns></returns>
        public IEnumerable<Type> GetHandlersForEvent(Type eventData)
        {
            if (HasRegisterForEvent(eventData))
            {
                return _eventAndHandlerMapping[eventData];
            }

            return new List<Type>();
        }

        /// <summary>
        /// 根据eventname获取handler
        /// </summary>
        /// <param name="eventName"></param>
        /// <returns></returns>
        public Type GetEventTypeByName(string eventName)
        {
            return _eventAndHandlerMapping.Keys.FirstOrDefault(eh => eh.Name == eventName);
        }

        public bool IsEmpty => !_eventAndHandlerMapping.Keys.Any();

        public void Clear() => _eventAndHandlerMapping.Clear();
    }
}